package com.dream.springmvc;


import com.dream.springmvc.filter.*;
import com.dream.springmvc.filter.operators.DatetimeOperator;
import com.dream.springmvc.filter.operators.DoubleOperator;
import com.dream.springmvc.filter.operators.ListStringOperator;
import com.dream.springmvc.filter.operators.StringOperator;
import com.dream.springmvc.value.*;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;

/**
 * @author panwen
 */
@Component
public class FilterDeserializer extends JsonDeserializer<FilterBase<?>> {

    @Override
    public FilterBase<?> deserialize(JsonParser p,
                                     DeserializationContext ctx)
            throws IOException, JacksonException {
        JsonNode root = p.getCodec().readTree(p);

        String fieldId = root.get("fieldId").asText();
        if (!StringUtils.hasText(fieldId)) {
            throw new RuntimeException("fieldId must exists.");
        }

        FieldTypeEnum type = getById(fieldId);

        return gen(type, root);
    }

    private FieldTypeEnum getById(String fieldId) {
        return null;
    }

    private FilterBase<?> gen(FieldTypeEnum type , JsonNode root) {
        switch (type) {
            case SINGLE_LINE_TEXT -> {
                SingleLineTextFilter filter = new SingleLineTextFilter();
                filter.setFieldId(root.get("fieldId").asText());
                filter.setOp(StringOperator.valueOf(root.get("op").asText()));
                filter.setVal(new SingleLineTextValue(root.get("val").asText()));
                return filter;
            }
            case MULTILINE_TEXT -> {
                MultiLineTextFilter filter = new MultiLineTextFilter();
                filter.setFieldId(root.get("fieldId").asText());
                filter.setOp(StringOperator.valueOf(root.get("op").asText()));
                filter.setVal(new MultiLineTextValue(root.get("val").asText()));
                return filter;
            }
            case SINGLE_SELECT -> {
                SingleSelectFilter filter = new SingleSelectFilter();
                filter.setFieldId(root.get("fieldId").asText());
                filter.setOp(StringOperator.valueOf(root.get("op").asText()));
                filter.setVal(new SingleSelectValue(root.get("val").asText()));
                return filter;
            }
            case MULTI_SELECT -> {
                MultiSelectFilter filter = new MultiSelectFilter();
                filter.setFieldId(root.get("fieldId").asText());
                filter.setOp(ListStringOperator.valueOf(root.get("op").asText()));
                filter.setVal(new MultiSelectValue(root.findValuesAsText("val")));
                return filter;
            }
            case NUMBER -> {
                NumberFilter filter = new NumberFilter();
                filter.setFieldId(root.get("fieldId").asText());
                filter.setOp(DoubleOperator.valueOf(root.get("op").asText()));
                filter.setVal(new NumberValue(root.get("val").asDouble()));
                return filter;
            }
            case AMOUNT -> {
                AmountFilter filter = new AmountFilter();
                filter.setFieldId(root.get("fieldId").asText());
                filter.setOp(DoubleOperator.valueOf(root.get("op").asText()));
                filter.setVal(new AmountValue(root.get("val").asDouble(), root.get("unit").asText()));
                return filter;
            }
            case DATE -> {
                DatetimeFilter filter = new DatetimeFilter();
                filter.setFieldId(root.get("fieldId").asText());
                filter.setOp(DatetimeOperator.valueOf(root.get("op").asText()));
                filter.setVal(DatetimeValue.fromJson(root.get("val").asText()));
                if (root.has("secondVal")) {
                    filter.setSecondVal(DatetimeValue.fromJson(root.get("secondVal").asText()));
                }
                return filter;
            }
            default ->
                throw new RuntimeException("not support type.");
        }
    }
}
